Key Derivation Functions (KDF)

Key derivation is the process of producing one or more keys from a master key, also known as key stretching. The master key can be a password, passphrase, or a Diffie-Hellman negotiated shared key.

Let's propose our simple KDF as:

$DK = HASH(password)$

Exercise

  • Why this KDF is not good?
  • There is no noise. Same password, produces same key. (add some randomness)
  • It's too fast to calculate, therefore easy to brute-force. (add iterations, use more expensive functions)

$DK = KDF(password, salt, iterations)$

PBKDF2 (Password-Based Key Derivation Function 2)

PBKDF2 is part of PKCS, and replaces the earlier PBKDF1. We need to pass a hashing function that will be used as the HMAC, number of iterations to mitigate brute-force attack, and a salt for rainbow tables.

$DK = PBKDF2(PRP, password, salt, iterations, keylen)$

For example in your wireless communication a key is derived as the following:

$Key = PBKDF2(HMAC−SHA1, passphrase, ssid, 4096, 256)$


In [ ]:
import os
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC
from cryptography.hazmat.backends import default_backend
salt = os.urandom(16)

# key derivation
kdf = PBKDF2HMAC(
    algorithm=hashes.SHA256(),
    length=32,
    salt=salt,
    iterations=100000,
    backend=default_backend())

key = kdf.derive(b"THE_SECRET_PASSWORD")

In [ ]:
import base64

print(key, len(key))
print(base64.b64encode(key))

In [ ]:
# Key verification
kdf = PBKDF2HMAC(
    algorithm=hashes.SHA256(),
    length=32,
    salt=salt,
    iterations=100000,
    backend=default_backend())

kdf.verify(b"THE_SECRET_PASSWORD", key)

Password Storage

We can use PBKDF2 for password storage as well. However, it is recommended to use scrypt that requires large amount of memory instead of just high computation demand.